package com.bee.commons.web.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 伪rpc接口日志，通过切面打印
 *
 * @author Damin.yang
 * @date 2019/08/26 16:45
 */
@Component
@Aspect
@Slf4j
public class WebLogAspect {

    private static final int FIVE_SECONDS = 5 * 1000;
    private static final ThreadLocal<Long> START = new ThreadLocal<>();

    @Pointcut("execution(public * com.bee..*.controller..*.*(..))")
    public void clientLogAspect() {}

    @Before("clientLogAspect()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(attributes==null){
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        log.info(">>> REQUEST 【{}】 --> URI : {}, PARAMS : {}",
                Thread.currentThread().getName(), request.getRequestURI(), JSON.toJSONString(request.getParameterMap()));

        START.set(System.currentTimeMillis());
    }

    @AfterReturning(returning = "result", pointcut = "clientLogAspect()")
    public void doAfterReturning(Object result) {

        long cost = System.currentTimeMillis() - START.get();

        if (cost > FIVE_SECONDS) {
            log.warn(">>> REQUEST 【{}】 TOO SLOW --> COSTS : {}, RESPONSE : {}",
                    Thread.currentThread().getName(), cost, JSON.toJSONString(result));
        } else {
            log.info(">>> REQUEST 【{}】 --> COSTS : {}, RESPONSE : {}",
                    Thread.currentThread().getName(), cost, JSON.toJSONString(result));
        }
        START.remove();

    }
    @AfterThrowing(throwing = "exception", pointcut = "clientLogAspect()")
    public void afterThrowing(Exception exception){
        START.remove();
    }

}
